home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / blf082b / ufg.c < prev   
C/C++ Source or Header  |  1993-12-11  |  15KB  |  672 lines

  1. /*
  2.  *    BloufGate
  3.  *    Convert RFC mail/news to Fidonet PKTs
  4.  *
  5.  *    Public Domain: may be copied and sold freely
  6.  */
  7.  
  8. #include "blouf.h"
  9.  
  10. /* idea: user setable gatekw, bin support, large unbatch */
  11. /* ----------------------------------------------------- Local globs */
  12.  
  13. int     gated=0; /* News messages gated */
  14. char    *buffer; /* unbatcher buffer - should be dynamic */
  15.  
  16. /* ------------------------------------------------- Gatemail tables */
  17.  
  18. enum keywords {
  19.     From, To, Date, Newsgroups, Subject, Msgid, Path, ReplyTo, Sender,
  20.     Followup, Expires, References, Control, Distrib, Organization,
  21.     Keywords, Summary, Approved, Lines, InReplyTo};
  22. #define nkw (InReplyTo+1)
  23.  
  24. char kwtext[nkw][13] = {
  25.     "From", "To", "Date", "Newsgroups", "Subject", "Message-ID",
  26.     "Path", "Reply-To", "Sender", "Followup-To", "Expires",
  27.     "References", "Control", "Distribution", "Organization",
  28.     "Keywords", "Summary", "Approved", "Lines", "In-Reply-To"};
  29.  
  30. /* ----------------------------------------------- Message gate */
  31.  
  32. /* 
  33.  *    Convert a rfc news/mail file to an already opened type-2 packet 
  34.  */
  35.  
  36. int process_rfcfile(char *file, FILE *packet, char *to_envel)
  37. {
  38.     /* incoming mail */
  39.     FILE   *msgtext;
  40.     char   Header[nkw][BLFSTR];
  41.     long   startm;
  42.     /* general purpose var */
  43.     char   oneline[BLFSTR], temp[BLFSTR];
  44.     int    i, j, npart, extline;
  45.     long   len;
  46.     char  *ptr;
  47.     /* outgoing mail */
  48.     int    gotto=0;
  49.     long   gatekw=0;
  50.     char   area[MAXCROSS][BLFSTR];
  51.     char   msgsubject[BLFSTR];
  52.     int    cross,icros;
  53.     struct tm msgtime;
  54.     BFIDOUSER msgfrom,msgto;
  55.     
  56.     /* check */
  57.     if(!packet)
  58.     {
  59.         logline("?Invalid packet handle");
  60.         return FAIL;
  61.     }
  62.     
  63.     /* open data file */
  64.     msgtext=fopen(file,"rb"); /* "rb" for compatibility with fseek()/ftell() */
  65.     if(!msgtext)
  66.         return FAIL;
  67.     
  68.     /* Init header strings */
  69.     for (i=0; i<nkw; i++)
  70.         Header[i][0] = 0;
  71.     
  72.     /* Decode header */
  73.     extline = 0;
  74.     while (!feof(msgtext)) 
  75.     {
  76.         
  77.         /* Read a line */
  78.         if(fblfgets(oneline,BLFSTR-2,msgtext)==NULL)
  79.         {
  80.             logline("?Error while reading header of %s",file);
  81.             fclose(msgtext);
  82.             return FAIL; /* File error */
  83.         }
  84.         
  85.         /* end of header */
  86.         if (extline && (oneline[0] == '\n')) break;
  87.         
  88.         /* Compare the current line with know headers */
  89.         for (i=0; i<nkw; i++)
  90.         {
  91.             len = (int) strlen(kwtext[i]);
  92.             if (strnicmp (oneline, kwtext[i],(size_t) len) == 0)
  93.             {
  94.                 j = (int) len+2;
  95.                 while ((oneline[j] == ' ') & (oneline[j] != 0))
  96.                     j++;
  97.                 if(strlen(oneline+j)>=BLFSTR)
  98.                     oneline[j+BLFSTR-1]=0;
  99.                 strcpy (Header[i], oneline+j);
  100.                 Header[i][strlen(Header[i])-1] = '\0';
  101.                 if (i != Path) 
  102.                     extline = 1;
  103.                 break;
  104.             }
  105.         }
  106.     }
  107.     /* Header now read */
  108.     
  109.     /* If !from, use reply-to */
  110.     if (Header[From][0] == '\0')
  111.         strcpy (Header[From], Header[ReplyTo]);
  112.     if (Header[From][0] == '\0')
  113.         strcpy(Header[From],"unknown@nowhere");
  114.     
  115.     /* Verify that we are not the sender */
  116.     sprintf (temp, "bloufgate@%s.", cf->uuname);
  117.     if (strncmp(Header[Sender], temp, strlen(temp)) == 0)
  118.     {
  119.         printf("Message from us.\n");
  120.         fclose(msgtext);
  121.         return FAIL;
  122.     }
  123.     
  124. #ifdef KILL_DUPES
  125.     /* Check dupe on Message-ID */
  126.     if (Header[Msgid][0]) {
  127.         char *ptr1, *ptr2; 
  128.         
  129.         ptr1 = strchr(Header[Msgid], '<');
  130.         ptr2 = strchr(Header[Msgid], '>');
  131.         if (ptr1 && ptr2 && ptr1 < ptr2) 
  132.         { /* we have a msgid */
  133.             strncpy(temp, ptr1, ptr2-ptr1+1);
  134.             temp[ptr2-ptr1+1] = '\0';
  135.             /*logline("-Message-ID: %s", temp);*/
  136.             if (dupechk_seen(temp)) 
  137.             {
  138.                 logline("?Duplicate message skipped (ID: %s)",temp);
  139.                 fclose(msgtext);
  140.                 return FAIL;
  141.             }
  142.         }
  143.         else
  144.         {
  145.             logline("=Invalid or no Message-ID, message skipped");
  146.             fclose(msgtext);
  147.             return FAIL;
  148.         }
  149.     }
  150. #endif
  151.  
  152.     /* Convert newsgroups to areas */
  153.     cross=-1; /* Nothing (mail?) */
  154.  
  155.     if(Header[Newsgroups][0])
  156.     {
  157.         strcpy(temp,Header[Newsgroups]);
  158.         ptr=temp;
  159.         /* parse newsgroup line */
  160.         do
  161.         {
  162.             char *ptr2;
  163.             GATENEWS *local;
  164.         
  165.             /* extract one newsgroup name */
  166.             ptr2=strchr(ptr,',');
  167.             if(ptr2)
  168.                 *ptr2++=0;
  169.             strcpy(temp,ptr);
  170.             
  171.             local=area_unix2fido(temp);
  172.             if(local)
  173.             {   /* gated group */
  174.                 if(++cross<MAXCROSS)
  175.                     strcpy(area[cross],local->fido);
  176.             }
  177.             else
  178.             {
  179. /* FIXME support binary groups
  180.                 local=area_unix2file(temp);
  181.                 if(local)
  182.                 {
  183.                 
  184.                     return SUCCESS;
  185.                 }
  186. */
  187.             }
  188.             ptr=ptr2;
  189.         } while(ptr); /* end of newsgroup */
  190.     }
  191.     
  192.     /* convert date */
  193.     strdate2tm(Header[Date],&msgtime);
  194.     
  195.     /** TO **/
  196.     if(Header[To][0]!=0)
  197.     {
  198.         norm_rfc(Header[To],temp,msgto.name);
  199.         strcpy(Header[To],temp);
  200.         if(rfc2fido(&msgto, to_envel!=NULL ? to_envel : Header[To])==SUCCESS)
  201.             gotto++;
  202.     }
  203.     
  204.     /** FROM **/
  205.     norm_rfc(Header[From],temp,msgfrom.name);
  206.     strcpy(Header[From],temp);
  207.     
  208.     if(strlen(msgfrom.name)==0)
  209.     { /* no name field use login to avoid empty fido from */
  210.         char *ptr;
  211.         ptr=strchr(temp,'@');
  212.         if(ptr)
  213.             *ptr=0;
  214.         strcpy(msgfrom.name,temp);
  215.     }
  216.     
  217.     msgfrom.zone=cf->o_zone;
  218.     msgfrom.net=cf->o_net;
  219.     msgfrom.node=cf->o_node;
  220.     msgfrom.point=cf->o_point;
  221.     
  222.     /** SUBJECT **/
  223.     strcpy (msgsubject, Header[Subject]);
  224.     if(strlen(msgsubject)>71)
  225.         msgsubject[71]='\0'; /* truncate at max fsc subject field len */
  226.     
  227.     /* start of the message text */
  228.     startm=ftell(msgtext);
  229.     if(startm<0)
  230.     {
  231.         logline("?ftell() error");
  232.         fclose(msgtext);
  233.         return FAIL;
  234.     }
  235.     
  236.     /*  WRITE ECHOMAILS if it is a conference mail */
  237.     for(icros=0;icros<=cross;icros++) /* while(cross>=0) */
  238.     {
  239.         /* log something */
  240.         printf("Writing echomail from %s -> %s\n",Header[From],area[icros]);
  241.         
  242.         /* convert echomail's to */
  243.         ptr = strstr(Header[InReplyTo], "'s message");
  244.         if (ptr)
  245.         {
  246.             *ptr = 0;
  247.             strcpy(msgto.name,Header[InReplyTo]);
  248.         }
  249.         else
  250.             strcpy(msgto.name,"All");
  251.         
  252.         npart = 0; /* Cut long messages */
  253.         
  254.         /* rewind to start of message text */
  255.         if(fseek(msgtext,startm,SEEK_SET)<0)
  256.         {
  257.             logline("?fseek error");
  258.             fclose(msgtext);
  259.             return FAIL;
  260.         }
  261.         
  262.         do /* large message loop */
  263.         {
  264.             /* multiple parts subjects */
  265.             if (npart)
  266.                 sprintf (msgsubject, "[%d] %s", npart+1, Header[Subject]);
  267.             
  268.             /*** Write Message Header in Fido packet */
  269.             openpktmessage(packet,area[icros],&msgfrom,&msgto,
  270.                             msgsubject,0,&msgtime);
  271.  
  272. #ifdef USE_CHRS
  273.             fprintf(packet,"\01CHRS: LATIN-1 2\r");
  274. #endif            
  275. #ifdef USE_RFCID
  276.             if(Header[Msgid][0])
  277.             {
  278.                 ptr=strchr(Header[Msgid],'>');
  279.                 if(ptr)
  280.                     *ptr=0;
  281.                 ptr=strchr(Header[Msgid],'<');
  282.                 if(ptr)
  283.                 {
  284.                     ptr++;
  285.                     fprintf(packet,"\01%s %s\r",RFCIDKLUDGE,ptr);
  286.                 }
  287.             }
  288. #endif
  289.             
  290.             /* fsc-0035 support */
  291.             if(cf->fsc0035==TRUE)
  292.             {
  293.                 fprintf(packet,"\01REPLYADDR: %s\r",Header[From]);
  294.                 fprintf(packet,"\01REPLYTO: %d:%d/%d Uucp\r",cf->o_zone,
  295.                 cf->o_net,cf->o_node);
  296.             }
  297.             
  298.             /* text tags for information at the beginning of the message */
  299.             gatekw=Set(From);
  300.             /* add Reply-To if different than From */
  301.             if (strcmp(Header[ReplyTo], Header[From]) != 0)
  302.                 gatekw |= Set(ReplyTo);
  303.             /* add Newsgroups if Crosspost */
  304.             if (strscan(',', Header[Newsgroups]) != -1)
  305.                 gatekw |= Set(Newsgroups);
  306.             /* ajoute Followup-To si different du newsgroup */
  307.             if (/*(strcmp(Header[Followup], group) != 0) && */ (strcmp(Header[Followup], Header[Newsgroups]) != 0))
  308.                 gatekw |= Set(Followup);
  309.             
  310.             /* write them */
  311.             for (i=0; i<nkw; i++)
  312.             {
  313.                 if ((Header[i][0] != 0) && (Set(i) & gatekw))
  314.                     fprintf (packet, "%s: %s\r", kwtext[i], Header[i]);
  315.             }
  316.             fprintf(packet,"\r");
  317.             
  318.             /* Copy the message text itself */
  319.             len = 0;
  320.             while (fgets(temp,sizeof(temp)-1,msgtext))
  321.             {
  322.                 /* convert unix lf to fido cr */
  323.                 for(j=0;j<((int)strlen(temp));j++)
  324.                 {
  325.                     if(temp[j]=='\n' && (j==0 || temp[j-1]!='\r'))
  326.                         temp[j]='\r';
  327.                 }
  328.                 
  329.                 fputs(temp,packet);
  330.                 
  331.                 /* verify lenght */
  332.                 len+=strlen(temp);
  333.                 if (len > cf->maxsize)
  334.                 {
  335.                     fprintf (packet, "\r      (Post splitted at gateway, will continue on next message)\r");
  336.                     npart++;
  337.                     break;
  338.                 }
  339.             }
  340.             
  341.             /* The end of the message text (origin) */
  342.             fprintf (packet, "\r--- %s %s\r", ProgName, Version);
  343.             /* Origin line */
  344.             fprintf (packet, " * Origin: %s (%d:%d/%d.%d)\r", cf->origin,
  345.                     cf->o_zone,cf->o_net,cf->o_node,cf->o_point);
  346.             /* Seenby and path */
  347.             fprintf (packet, "SEEN-BY: %d/%d %d/%d\r", cf->o_net, cf->o_node,
  348.                     cf->td_net, cf->td_node);
  349.             fprintf (packet, "\01PATH: %d/%d\r", cf->td_net, cf->td_node);
  350.             
  351.             /* Next message */
  352.             closepktmessage(packet);
  353.             
  354.         } while (!feof(msgtext) && npart<BLF_MAXNPART);
  355.         gated++;
  356.     } /* End crosspost loop */
  357.     
  358.     /* write NETMAIL message */
  359.     if(cross<0)
  360.     {
  361.         if(Header[Newsgroups][0])
  362.         {
  363.             logline("?Ungated news message to newsgroups: %s",Header[Newsgroups]);
  364.             fclose(msgtext);
  365.             return FAIL;
  366.         }
  367.         
  368.         if(!gotto || !findnode(msgto.zone,msgto.net,msgto.node))
  369.         { /* bounce bad mail */
  370.             if(!gotto) /* no to */
  371.                 bounce_net(BOUNCE,"Can't parse fidonet address",
  372.                 Header[From],Header[Msgid],Header[To]);
  373.             else /* unlisted */
  374.                 bounce_net(BOUNCE,"Message to unlisted fidonet node",
  375.                     Header[From],Header[Msgid],Header[To]);
  376.         }
  377.         else
  378.         {
  379.             logline("+Netmail from %s to %s (%d:%d/%d.%d)",Header[From],
  380.                     msgto.name,msgto.zone,msgto.net,msgto.node,msgto.point);
  381.             
  382.             /*** Write Message Header in Fido packet */
  383.             openpktmessage(packet,NULL,&msgfrom,&msgto,
  384.                         msgsubject,0,&msgtime);
  385.             
  386.             /* text tags for information at the beginning of the message */
  387.             gatekw=Set(From)+Set(Organization);
  388.             /* add Reply-To if different than From */
  389.             if (strcmp(Header[ReplyTo], Header[From]) != 0)
  390.                 gatekw |= Set(ReplyTo);
  391.         
  392.             /* write them */
  393.             for (i=0; i<nkw; i++)
  394.             {
  395.                 if ((Header[i][0] != 0) && (Set(i) & gatekw))
  396.                     fprintf (packet, "%s: %s\r", kwtext[i], Header[i]);
  397.             }
  398.             fprintf(packet,"\r");
  399.         
  400.             /* Copy the message text itself */
  401.             len = 0;
  402.             while (fgets(temp,sizeof(temp)-1,msgtext))
  403.             {
  404.                 /* convert unix lf to fido cr */
  405.                 for(j=0;j<((int)strlen(temp));j++)
  406.                 {
  407.                     if(temp[j]=='\n' && (j==0 || temp[j-1]!='\r'))
  408.                         temp[j]='\r';
  409.                 }
  410.                 
  411.                 fputs(temp,packet);
  412.                 
  413.                 /* verify lenght */
  414.                 len+=strlen(temp);
  415.                 if (len > cf->maxsize)
  416.                 {
  417.                     fprintf(packet, "\r====================================================\r"
  418.                             "Message TRUNCATED at gateway. It is annoying practice\r"
  419.                             "to send large mails over Fido/Usenet gateways.\r");
  420.                     break;
  421.                 }
  422.             
  423.             }
  424.             
  425.             /* write RFC header behind kludges at the message end */
  426.             fseek(msgtext,0,SEEK_SET);
  427.             fprintf(packet,"\r\01=====================================================\r"
  428.                 "\01Original RFC message header follow:\r\r");
  429.             while (fgets(temp,sizeof(temp)-1,msgtext))
  430.             {
  431.                 /* convert unix lf to fido cr */
  432.                 for(j=0;j<((int)strlen(temp));j++)
  433.                 {
  434.                     if(temp[j]=='\n' && (j==0 || temp[j-1]!='\r'))
  435.                         temp[j]='\r';
  436.                 }
  437.                 
  438.                 fprintf(packet,"\01%s",temp);
  439.                 if(ftell(msgtext)>=startm-1)
  440.                     break;
  441.             }
  442.             
  443.             closepktmessage(packet);
  444.             gated++;
  445.         }
  446.     }
  447.     
  448.     fclose(msgtext);
  449.     
  450.     return SUCCESS;
  451. }
  452.  
  453. /*
  454.  *    Process a new batch
  455.  */
  456.  
  457. int process_news(char *name, FILE *pkt)
  458. {
  459.     FILE *idx;
  460.     FILE *fhdle;
  461.     size_t len;
  462.     int message=1;
  463.     int bad=0;
  464.     int first=0;
  465.     char temp[BLFSTR];
  466.     char outname[BLFSTR];
  467.     
  468.     buffer=malloc((size_t)BLF_BUFSIZE);
  469.     if(!buffer)
  470.     {
  471.         logline("?Can't malloc unbatch buffer.");
  472.         return FAIL;
  473.     }
  474.     
  475.     /* create outname */
  476.     sprintf(outname,"%s%c_BLOUF_.TMP",cf->tempdir,BLF_DSEPAR);
  477.  
  478.     /* open input file */
  479.     logline("-Unbatching %s",name);
  480.     idx=fopen(name,"rb");
  481.     
  482.     /* check handle */
  483.     if(!idx)
  484.     {
  485.         if(name)
  486.             logline("?Can't open %s!",name);
  487.         bad++;
  488.     }
  489.     else
  490.     {
  491.         while(!feof(idx)) /* read file */
  492.         {
  493.             if(fblfgets(temp,BLFSTR-2,idx)==NULL)
  494.             {
  495.                 printf("Can't read newline (out of synch?)\n");
  496.                 break;  /* exit loop */
  497.             }
  498.             
  499.             if(strncmp(RNEWSSTR,temp,strlen(RNEWSSTR)))
  500.             {
  501.                 if(first)
  502.                 {
  503.                     logline("?Out of synch at message %d!",message);
  504.                     break; /* exit loop */
  505.                 }
  506.                 else
  507.                 {
  508.                     fclose(idx);
  509.                     logline("-Single article mail");
  510.                     if(process_rfcfile(name,pkt,NULL)==FAIL)
  511.                         bad++;
  512.                     break; /* exit loop */
  513.                 }
  514.             }
  515.             
  516.             first++;
  517.             
  518.             len=(size_t) atol(temp+strlen(RNEWSSTR));
  519.             if(len<BLF_BUFSIZE)
  520.             {
  521.                 if(fread(buffer,len,1,idx)==1)
  522.                 {
  523.                     /* writing temp file */
  524.                     fhdle=fopen(outname,"wb");
  525.                     if(!fhdle)
  526.                     {
  527.                         logline("?Can't open temp file %s",outname);
  528.                         fclose(idx);
  529.                         bad++;
  530.                         break; /* exit loop */
  531.                     }
  532.                     else
  533.                     {
  534.                         if(fwrite(buffer,len,1,fhdle)!=1)
  535.                             logline("?Write error on outgoing message %s",outname);
  536.                         fclose(fhdle);
  537.                     }
  538.                     
  539.                     /* gate temp file */
  540.                     if(process_rfcfile(outname,pkt,NULL)==FAIL)
  541.                     {
  542.                         logline("?Can't gate message %d.",message);
  543.                         bad++;
  544.                     }
  545.                     
  546.                     /* delete temp file */
  547.                     if(remove(outname))
  548.                         logline("?Can't delete %s",outname);
  549.                 }
  550.                 else
  551.                 {
  552.                     logline("?Can't read message %d.",message);
  553.                     break;
  554.                 }
  555.             }
  556.             else
  557.             {
  558.                 logline("?Skipping message %d (too long: %d)",message,(long) len);
  559.                 fseek(idx,(long) len,SEEK_CUR);
  560.             }
  561.             message++;
  562.         } /* end read file loop */
  563.         
  564.         fclose(idx);
  565.     }
  566.     logline("-%d news messages gated",gated);
  567.     
  568.     if(cf->keep==FALSE)
  569.     {
  570.         if(!bad && name)
  571.             remove(name);
  572.     }
  573.     
  574.     free(buffer);
  575.     if(bad)
  576.         return FAIL;
  577.     return SUCCESS;
  578. }
  579.  
  580. /*
  581.  *    Process a mailbox file
  582.  */
  583.  
  584. int process_mailbox(char *name, FILE *pkt, char *to_env)
  585. {
  586.     FILE *idx;
  587.     FILE *outf=NULL;
  588.     int message=1;
  589.     int bad=0;
  590.     int end=0;
  591.     char temp[BLFSTR];
  592.     char outname[BLFSTR];
  593.     
  594.     /* create outname */
  595.     sprintf(outname,"%s%c_BLOUF_.TMP",cf->tempdir,BLF_DSEPAR);
  596.     
  597.     /* open file */
  598.     logline("-Processing mailbox file %s",name);
  599.     idx=fopen(name,"r");
  600.         
  601.     /* check file handle */
  602.     if(!idx)
  603.     {
  604.         logline("?Can't open %s!",name);
  605.         bad++;
  606.     }
  607.     else
  608.     {
  609.         while(!feof(idx))
  610.         {
  611.             if(fblfgets(temp,BLFSTR-2,idx)==NULL)
  612.             {
  613.                 printf("Can't read newline\n");
  614.                 end++;
  615.             }
  616.             
  617.             if(!strncmp(temp,"From ",strlen("From ")) || end) /* improve separator detection? */
  618.             { /* this is another mail */
  619.                 /* close last message temp file if there's one*/
  620.                 if(outf)
  621.                 {
  622.                     fclose(outf);
  623.                     outf=NULL;
  624.                 
  625.                     /* gate temp file */
  626.                     if(process_rfcfile(outname,pkt,to_env)==FAIL)
  627.                     {
  628.                         logline("?Can't gate message %d.",message);
  629.                         bad++;
  630.                     }
  631.                     message++;
  632.  
  633.                     /* delete temp file */
  634.                     if(remove(outname))
  635.                         logline("?Can't delete %s",outname);
  636.                 }
  637.             }
  638.  
  639.             if(end) 
  640.                 break;
  641.             
  642.             /* if temp file is not open create it */
  643.             if(!outf)
  644.             {
  645.                 /* writing temp file */
  646.                 outf=fopen(outname,"wb");
  647.                 if(!outf)
  648.                 {
  649.                     logline("?Can't open temp file %s",outname);
  650.                     fclose(idx);
  651.                     return FAIL;
  652.                 }
  653.             }
  654.             
  655.             /* copy string to temp file */
  656.             fputs(temp,outf);
  657.         }
  658.         fclose(idx);
  659.     }
  660.     logline("-%d news messages gated",gated);
  661.     
  662.     if(cf->keep==FALSE)
  663.     {
  664.         if(!bad && name)
  665.             remove(name);
  666.     }
  667.  
  668.     if(bad)
  669.         return FAIL;
  670.     return SUCCESS;
  671. }
  672. /* end of ufg.c */